// @flow

function sum(a: number, b: number) {
    // // 对于强类型来说没比要的代码!
    // if (typeof a !== "number" || typeof b !== "number") {
    //     throw new TypeError("arguments must be a number");
    // }
    return a + b;
}
sum(100, 100);
sum("100", "100");

// flow还可以推断变量的类型
function square(n) {
    return n * n;
}
square("100");

// 标记变量和函数返回值的类型
let num: number;

// 函数返回值
function foo(): number {
    return 100;
}
// 没有返回值会返回undefined依旧会报语法错误
// 没有返回值的函数标记为
function boo(): void {
    return 100;
}
// 原始类型 ===========================================================
// String Number Boolean Null Undefined Symbol BigInt
const a: string = "undefined";
const b: number = Infinity; //NaN //100
const c: boolean = true; // false
const d: null = null;
const e: void = undefined;
const f: symbol = Symbol();

// 数组类型 泛型 ========================================================
const arr1: Array<number> = [1, 2, 3]; //全部由数字组成的数组
const arr2: number[] = [1, 2, 3]; //全部由数字组成的数组
// 固定长度数组 => 元组
const foo: [string, number] = ["foo", 100];

// 对象 定长 ===========================================================
const obj1: { foo: string, bar: number } = { foo: "string", bar: 100 };
// 加?成为可选对象
const obj2: { foo?: string, bar: number } = { bar: 100 };
// 键值对集合
// 不定长 限制类型
const obj3: { [string]: string } = {};
obj3.key1 = "value";
obj3.key2 = 100;

// 函数类型 ============================================================
// 存放函数的变量类型
function foo(callback: (string, number) => void) {
    callback("string", 100);
}
foo(function (str, num) {
    // 不可以有返回值
    // return undefined
});
// 特殊类型 =============================================================
// 字面量
const g: "foo" = "foo"; //'foo1'会报错
// 联合类型 或类型
const type: "success" | "warning" | "danger" = "success";
const h: string | number = "string";
// 类型别名
type stringOrNum = string | number;
const i: stringOrNum = "string";

// maybe
// null undefined 也可
// ?number相当于 number | null | void
const gender: ?number = null;

//  mixed 任意类型的值
function passMixed(value: mixed) {
    // 报语法错误 必须先清楚变量的类型
    if (typeof value === "string") {
        value.substr(1);
    }
    if (typeof value === "number") {
        value * value;
    }
}

passMixed("string");
passMixed(100);

// any
function passAny(value: any) {
    // 不会报语法错误
    value.substr(1);
    value * value;
}
passAny("string");
passAny(100);

// any弱类型 mixed强类型
// mixed安全 any不安全 为了兼容老代码 弱类型 动态类型
